package tt.dz.egobus.servicemanager.service.impl;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tt.dz.egobus.api.ResponseBack;
import tt.dz.egobus.api.managerservice.manager.*;
import tt.dz.egobus.api.usercenter.user.UserInfoBack;
import tt.dz.egobus.base.dao.BaseDao;
import tt.dz.egobus.bean.BusinessStatus;
import tt.dz.egobus.bean.Pagination;
import tt.dz.egobus.servicemanager.base.service.AbstractExtendService;
import tt.dz.egobus.servicemanager.bean.CornConverter;
import tt.dz.egobus.servicemanager.business.convert.BespeakTimeRedisRestoreConvertor;
import tt.dz.egobus.servicemanager.business.point.AddressPoint;
import tt.dz.egobus.servicemanager.business.point.BusPoint;
import tt.dz.egobus.servicemanager.dao.BusinessServiceInfoDao;
import tt.dz.egobus.servicemanager.entities.BusService;
import tt.dz.egobus.servicemanager.entities.BusinessService;
import tt.dz.egobus.servicemanager.entities.BusinessServiceInfo;
import tt.dz.egobus.servicemanager.entities.DriverRegisterBusRelative;
import tt.dz.egobus.servicemanager.facade.interator.FacadeFactory;
import tt.dz.egobus.servicemanager.facade.interator.FacadeFactoryLoggerInterceptorHolder;
import tt.dz.egobus.servicemanager.facade.user.UserCenterFacade;
import tt.dz.egobus.servicemanager.service.BusServiceService;
import tt.dz.egobus.servicemanager.service.BusinessServiceInfoService;
import tt.dz.egobus.servicemanager.util.DateUtils;
import tt.dz.egobus.servicemanager.vo.BusServiceViewVo;
import tt.dz.egobus.servicemanager.vo.BusinessFinishVo;
import tt.dz.egobus.servicemanager.vo.BusinessRequestVo;

import java.util.*;

import static tt.dz.egobus.api.managerservice.manager.PageVo.userTypeEnum.DRIVER;
import static tt.dz.egobus.api.managerservice.manager.PageVo.userTypeEnum.USER;
import static tt.dz.egobus.bean.BusinessStatus.BESPEAK_SUCCESS;

/**
 * @author Anson
 * @date 17-3-15
 * @name 业务详细服务层实现类
 * @since 1.0.3
 */
@Service("businessServiceInfoServiceImpl")
public class BusinessServiceInfoServiceImpl extends AbstractExtendService<BusinessServiceInfo, String> implements
        BusinessServiceInfoService {
    private static final Logger LOGGER = LoggerFactory.getLogger(BusinessServiceServiceImpl.class);


    @Autowired
    @Qualifier("busServiceServiceImpl")
    private BusServiceService busServiceService;

    @Autowired
    @Qualifier("businessServiceInfoDaoImpl")
    private BusinessServiceInfoDao dao;


    @Override
    protected BaseDao<BusinessServiceInfo, String> getSelfDao() {
        return this.dao;
    }

    @Override
    @Transactional
    public boolean saveBeginBusinessService(BusinessService businessService, BusPoint busPoint, BusinessRequestVo
            businessRequestVo, DriverRegisterBusRelative relative) {
        if (businessService == null || busPoint == null || businessRequestVo == null || StringUtils.isEmpty
                (businessService.getId()) || StringUtils.isEmpty(businessService.getBusinessId())) {
            return false;
        }
        LOGGER.info("业务详细服务层实现类saveBeginBusinessService");
        return doInsertBusinessInfo(businessService, busPoint, businessRequestVo, relative);
    }


    @Override
    @Transactional
    public boolean doSaveBusiness(BusinessService businessService, AddressPoint addressPoint) {
        if (businessService == null || addressPoint == null || StringUtils.isEmpty(businessService.getId()) ||
                StringUtils.isEmpty(businessService.getBusinessId())) {
            return false;
        }
        List<BusinessServiceInfo> list = this.getInfoByBusinessServiceId(businessService.getId());
        if (CollectionUtils.isEmpty(list) || list.size() != 1) {
            return false;
        }
        BusinessServiceInfo info = list.get(0);
        handlerDriverBaseInfo(businessService, info);
        //业务真正的开始地理位置，替换默认的地理位置
        info.setStartX(addressPoint.x());
        info.setStartY(addressPoint.y());
        info.setStartAddress(addressPoint.getAddress());
        //记录乘客上车时间
        info.setBoardingTime(new Date());
        try {
            this.dao.update(info);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * @param businessService 当前服务
     * @param info            详细信息
     * @author Anson
     * @date 17-9-2
     * @name 设置司机基本信息
     * @since 1.0.7
     */
    private void handlerDriverBaseInfo(BusinessService businessService, BusinessServiceInfo info) {
        String driverId = businessService.getDriverId();
        UserInfoBack driverInfo = getUserInfo(driverId);
        if (driverInfo != null) {
            info.setDriverName(driverInfo.getRealName());
            info.setPhoneNumber(driverInfo.getPhoneNumber());
        }
    }

    @Override
    @Transactional
    public BusinessServiceInfo getInfoByServiceId(String serviceId) {
        if (StringUtils.isEmpty(serviceId)) {
            return null;
        }
        List<BusinessServiceInfo> list = this.getInfoByBusinessServiceId(serviceId);
        if (CollectionUtils.isEmpty(list) || list.size() != 1) {
            return null;
        }
        return list.get(0);
    }

    @Override
    @Transactional
    public boolean doSaveFinish(BusinessServiceInfo info, BusinessBaseLimitStatus status, BusinessService
            businessService, BusinessFinishVo vo) {
        if (businessService == null || StringUtils.isEmpty(businessService.getId()) || StringUtils.isEmpty
                (businessService.getBusinessId()) || vo == null) {
            return false;
        }
        if (info == null) {
            info = this.getInfoByServiceId(businessService.getId());
        }
        if (info == null) {
            return false;
        }
        if (status == null) {
            status = info.getLimitStatus();
        }
        LOGGER.info("业务详细服务层实现类司机完成的vo={}", vo);
        info.setEndTime(vo.getEndTime());
        info.setEndAddress(vo.getAddress());
        info.setEndX(vo.getX());
        info.setEndY(vo.getY());
        info.setDistance(vo.getRealDistance());
        if (status != null) {
            info.setOrverTimeSeconds(status.getOverBaseTimeLimtSeconds());
        }
        try {
            this.dao.update(info);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    @Override
    @Transactional
    public BusinessServiceInfo getDriverLastestTaskInfo(String driverId) {
        if (StringUtils.isEmpty(driverId)) {
            return null;
        }
        String hqlNamedQuery = "getDriverLastestInfo";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("driverId", driverId);
        List<BusinessServiceInfo> list = (List<BusinessServiceInfo>) this.dao.list(hqlNamedQuery, params, 0, 1, null);
        return list == null || list.isEmpty() ? null : list.get(0);
    }

    @Override
    @Transactional
    public BusinessServiceInfo getInfoByBusinessId(String businessId) {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("eq#businessId", businessId);
        param.put("eq#isValidate", true);
        List<BusinessServiceInfo> ls = this.dao.list(param);
        if (CollectionUtils.isEmpty(ls)) {
            return null;
        }
        return ls.get(0);
    }


    @Transactional
    @Override
    public List<String> queryDriverBespeakUnDoneDates(String driverId) {
        List<String> datesList = new ArrayList<>();
        List<BusinessServiceInfo> ls = this.queryDriverBespeakUnDoneInfos(driverId);
        if (CollectionUtils.isEmpty(ls)) {
            return datesList;
        }
        CornConverter<Date, String> cornConverter = new BespeakTimeRedisRestoreConvertor();
        Converter<Date, String> dateStringConverter = cornConverter.convertCornA();
        for (BusinessServiceInfo info : ls) {
            if (info == null || info.getBespeakTime() == null) {
                continue;
            }
            datesList.add(dateStringConverter.convert(info.getBespeakTime()));
        }
        return datesList;
    }

    @Transactional
    @Override
    public List<BusinessServiceInfo> queryDriverBespeakUnDoneInfos(String driverId) {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("eq#bs.driverId", driverId);
        //预约成功,但不包括生效的预约
        param.put("eq#bs.status", BESPEAK_SUCCESS.getCode());
        param.put("eq#isValidate", true);
        List<BusinessServiceInfo> ls = this.dao.list(param);
        if (CollectionUtils.isEmpty(ls)) {
            return new ArrayList<>();
        }
        return ls;
    }

    @Transactional
    @Override
    public List<BusinessServiceInfo> getInfoByBusinessIds(String[] businessIds) {
        String hqlNamedQuery = "getBusinessServiceInfoByBusinessIds";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("businessId", businessIds);
        List<BusinessServiceInfo> list = (List<BusinessServiceInfo>) this.dao.list(hqlNamedQuery, params, 0, 0, null);
        return CollectionUtils.isEmpty(list) ? new ArrayList<>() : list;
    }

    @Transactional
    @Override
    public boolean isContainerDriverBespeakDate(String driverId, Date date) {
        String hqlNamedQuery = "isContainerDriverBespeakDate";
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("bespeakTime", DateUtils.DateToString(date, DateUtils.DATE_TO_STRING_SHORT_PATTERN));
        param.put("driverId", driverId);
        param.put("status", BusinessStatus.BESPEAK_SUCCESS.getCode());
        List<Number> count = (List<Number>) this.dao.list(hqlNamedQuery, param, 0, 0, null);
        return count.isEmpty() ? false : count.get(0).longValue() > 0;
    }

    @Override
    @Transactional
    public boolean doBespeakBusiness(BusinessService businessService, BusPoint busPoint, BusinessRequestVo
            businessRequestVo, DriverRegisterBusRelative relative) {
        if (businessService == null || busPoint == null || businessRequestVo == null || StringUtils.isEmpty
                (businessService.getId()) || StringUtils.isEmpty(businessService.getBusinessId())) {
            return false;
        }
        LOGGER.info("业务详细服务层实现类doBespeakBusiness");
        return doInsertBusinessInfo(businessService, busPoint, businessRequestVo, relative);
    }

    /**
     * @param businessService   当前所关联的业务详细
     * @param busPoint          司机当前接受派单地理位置
     * @param businessRequestVo 业务请求vo
     * @param relative
     * @author Anson
     * @date 17-8-30
     * @name 新增一个业务详细信息
     * @since 1.0.7
     */
    @Transactional
    private boolean doInsertBusinessInfo(BusinessService businessService, BusPoint busPoint, BusinessRequestVo
            businessRequestVo, DriverRegisterBusRelative relative) {
        BusinessServiceInfo info = new BusinessServiceInfo();
        UserRequestTypeInfo userRequestTypeInfo = businessRequestVo.getUserRequestInfo();
        info.setBusinessId(businessService.getBusinessId());
        info.setBusinessServiceId(businessService.getId());
        info.setIsValidate(true);
        if (userRequestTypeInfo != null) {
            info.setCreateTime(new Date(userRequestTypeInfo.getCreateTime()));
            long bespeakTime = userRequestTypeInfo.getBespeakTime();
            if (bespeakTime > 0) {
                info.setBespeakTime(new Date(bespeakTime));
            }
        }

        info.setAcceptX(busPoint.x());
        info.setAcceptY(busPoint.y());
        UserRequestAddressInfo userRequestAddressInfo = businessRequestVo.getUserRequestAddressInfo();
        if (userRequestAddressInfo != null) {
            //用户默认的开始的位置就是当前用户请求的位置
            AddressUnit onBusAddress = userRequestAddressInfo.getRequestOnStartAddress();
            if (onBusAddress != null) {
                info.setStartX(onBusAddress.getX());
                info.setStartY(onBusAddress.getY());
                info.setStartAddress(onBusAddress.getAddress());
            }
            //用户请求的地理位置
            info.setRequestStartX(onBusAddress.getX());
            info.setRequestStartY(onBusAddress.getY());
            info.setRequestStartAddress(onBusAddress.getAddress());
            AddressUnit onEndAddress = userRequestAddressInfo.getRequestOnEndAddress();
            //用户请求的结束的地理位置
            if (onEndAddress != null) {
                info.setRequestEndX(onEndAddress.getX());
                info.setRequestEndY(onEndAddress.getY());
                info.setRequestEndAddress(onEndAddress.getAddress());
            }
        }
        info.putBusServiceInfoJsonObject(this.busServiceViewVo(businessService.getBusinessCode()));
        info.setBusId(relative.getBusId());
        handlerDriverBaseInfo(businessService, info);
        UserRequestContactInfo userRequestContactInfo = businessRequestVo.getUserRequestContactInfo();
        if (userRequestContactInfo != null) {
            //用户请求派车的联系信息  [必须]
            ContactUnit userContact = userRequestContactInfo.getUserContact();
            //用户乘车的联系信息  [必须]
            ContactUnit passengerContact = userRequestContactInfo.getPassengerContact();
            if (userContact != null) {
                info.setUserName(userContact.getName());
                info.setUserPhone(userContact.getPhone());
            }
            if (passengerContact == null) {
                passengerContact = userContact;
            }
            if (passengerContact != null) {
                info.setPassengerName(passengerContact.getName());
                info.setPassengerPhone(passengerContact.getPhone());
            }
        }
        try {
            this.dao.save(info);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Transactional
    private List<BusinessServiceInfo> getInfoByBusinessServiceId(String businessServiceId) {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("eq#businessServiceId", businessServiceId);
        param.put("eq#isValidate", true);
        return this.dao.list(param);
    }

    @Transactional
    public Pagination<BusinessServiceInfo> queryBusinessInfoByPage(PageVo vo) {
        Map<String, Object> param = new HashMap<String, Object>();
        Integer type = vo.getType();
        if (DRIVER.getCode() == type) {
            param.put("eq#bs.driverId", vo.getUserId());
        }
        if (USER.getCode() == type) {
            param.put("eq#bs.userId", vo.getUserId());
        }
        param.put("eq#bs.status", BESPEAK_SUCCESS.getCode());
        param.put("eq#isValidate", true);
        int pageNumber = vo.getPageNumber();
        //按照创建时间倒排序
        List<String> orders = new ArrayList<>();
        orders.add("asc#bespeakTime");
        return this.dao.pagination(param, pageNumber, 10, orders);
    }


    @Transactional
    private BusServiceViewVo busServiceViewVo(int businessCode) {
        BusService busService = busServiceService.getBusServiceByBusinessCode(businessCode);
        BusServiceViewVo vo = new BusServiceViewVo();
        return busService == null ? vo : vo.view(busService);
    }

    private UserInfoBack getUserInfo(String userId) {
        FacadeFactory facadeFactory = FacadeFactoryLoggerInterceptorHolder.LOGGER_FACADE;
        UserCenterFacade userCenterFacade = facadeFactory.getBean("usercenter", UserCenterFacade.class);
        ResponseBack<UserInfoBack> infoBackResponseBack = userCenterFacade.findUserInfo(userId);
        if (infoBackResponseBack != null) {
            return infoBackResponseBack.getResult();
        }
        return null;

    }

}
